﻿using Kingdee.BOS.Core.DynamicForm.PlugIn;
using Kingdee.BOS.Core.DynamicForm.PlugIn.Args;
using Kingdee.BOS.DataEntity;
using Kingdee.BOS.Resource;
using Kingdee.BOS.ServiceHelper.FileServer;
using Kingdee.BOS.ServiceHelper;
using Kingdee.BOS.Util;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using Kingdee.BOS.Core.DynamicForm.PlugIn.ControlModel;
using Kingdee.BOS.Core.Metadata.ControlElement;
using Kingdee.BOS.Core.Metadata;
using Kingdee.BOS.JSON;
using Kingdee.BOS;
using System.Web;
using System.Security.Policy;
using Kingdee.BOS.Core.FileServer;
using System.Text.RegularExpressions;
using Kingdee.BOS.Core;
using System.IO;
using Kingdee.BOS.Log;
using Kingdee.BOS.ServiceHelper.Export;
using Kingdee.BOS.Core.DynamicForm;
using Kingdee.BOS.Core.Msg;
using Kingdee.BOS.KDThread;
using Kingdee.BOS.ServiceHelper.OSS;
using System.Reflection.Emit;
using Kingdee.BOS.BusinessEntity.OSS.LogModel;

namespace LianKe.DynamicFormPlugIn
{
    [Description("附件下载动态表单插件。")]
    [HotUpdate]
    public class FileDownLoadPlugIn : AbstractDynamicFormPlugIn
    {
        private const string _fileOpenButton = "FileOpenButton";

        private static ConcurrentDictionary<string, string> _downLoadUrlMap = new ConcurrentDictionary<string, string>();

        private string _url = string.Empty;

        private List<string> _urls;

        private string _linkText = string.Empty;

        private string _isRetain = string.Empty;

        private string _customDir = string.Empty;

        [DllImport("kernel32.dll")]
        public static extern IntPtr _lopen(string lpPathName, int iReadWrite);

        [DllImport("kernel32.dll")]
        public static extern bool CloseHandle(IntPtr hObject);

        public override void OnInitialize(InitializeEventArgs e)
        {
            base.OnInitialize(e);
            _url = ObjectUtils.GetString(((AbstractDynamicFormPlugIn)this).View.OpenParameter.GetCustomParameter("url"));
            _urls = ((AbstractDynamicFormPlugIn)this).View.OpenParameter.GetCustomParameter("urls") as List<string>;
            _linkText = ObjectUtils.GetString(((AbstractDynamicFormPlugIn)this).View.OpenParameter.GetCustomParameter("linktext"));
            _isRetain = ObjectUtils.GetString(((AbstractDynamicFormPlugIn)this).View.OpenParameter.GetCustomParameter("IsRetain"));
            _customDir = ObjectUtils.GetString(((AbstractDynamicFormPlugIn)this).View.OpenParameter.GetCustomParameter("customDir"));
        }
        public override void AfterBindData(EventArgs e)
        {
            base.AfterBindData(e);
            FileServerHelper.CheckIsFlowControlled(((AbstractDynamicFormPlugIn)this).View, (Enu_FlowCrlType)1);
            if (_urls != null)
            {
                InitDownloadLinkList();
                return;
            }
            InitDownloadLink();
            if ((int)((AbstractDynamicFormPlugIn)this).View.Context.ClientType == 1 && !SystemParameterServiceHelper.IsWpfDownloadByBrowser(((AbstractDynamicFormPlugIn)this).View.Context))
            {
                ((AbstractDynamicFormPlugIn)this).View.GetControl("FLabel").Text = ResManager.LoadKDString("文件生成成功，请点击以下链接，保存文件至本地，或者点击打开按钮直接打开文件。", "002420000024703", (SubSystemType)2, new object[0]);
            }
            else
            {
                ((AbstractDynamicFormPlugIn)this).View.GetControl("FileOpenButton").Visible = false;
            }
        }
        public override void BeforeClosed(BeforeClosedEventArgs e)
        {
            base.BeforeClosed(e);
            try
            {
                if (HttpContext.Current == null)
                {
                    return;
                }
                string text = ((AbstractDynamicFormPlugIn)this).View.OpenParameter.GetCustomParameter("IsStorageK3Cloud") as string;
                if (text == "0")
                {
                    if (_urls == null)
                    {
                        string fileId = ((AbstractDynamicFormPlugIn)this).View.OpenParameter.GetCustomParameter("id") as string;
                        DeleteExportCenterFile(fileId);
                    }
                    else
                    {
                        if (!(((AbstractDynamicFormPlugIn)this).View.OpenParameter.GetCustomParameter("ids") is List<string> list))
                        {
                            return;
                        }
                        {
                            foreach (string item in list)
                            {
                                DeleteExportCenterFile(item);
                            }
                            return;
                        }
                    }
                    return;
                }
                if (_urls != null)
                {
                    foreach (string url in _urls)
                    {
                        if (!ObjectUtils.IsNullOrEmptyOrWhiteSpace((object)url))
                        {
                            DeleteFile(url);
                        }
                    }
                    return;
                }
                if (!ObjectUtils.IsNullOrEmptyOrWhiteSpace((object)_url))
                {
                    DeleteFile(_url);
                }
            }
            catch (Exception ex)
            {
                LoggerWithContext.Error(((AbstractDynamicFormPlugIn)this).View.Context, "BOS-FileDownloadPlugin", "删除下载临时文件失败", ex);
            }
        }
        public override void ButtonClick(ButtonClickEventArgs e)
        {
            if (e.Cancel)
            {
                return;
            }
            if (StringUtils.EqualsIgnoreCase(e.Key, "FileOpenButton"))
            {
                string browserType = ((AbstractDynamicFormPlugIn)this).Context.ClientInfo.BrowserType;
                if (!ObjectUtils.IsNullOrEmptyOrWhiteSpace((object)browserType) && browserType.IndexOf("win", StringComparison.OrdinalIgnoreCase) < 0)
                {
                    ((AbstractDynamicFormPlugIn)this).View.ShowMessage(ResManager.LoadKDString("此操作系统不支持本地文件服务预览。", "002011030036656", (SubSystemType)2, new object[0]), (MessageBoxType)0);
                    return;
                }
                JSONObject val = new JSONObject();
                ((Dictionary<string, object>)(object)val)["action"] = "OpenRes";
                string appSiteOuterNetUrl = FileServerHelper.GetAppSiteOuterNetUrl(((AbstractDynamicFormPlugIn)this).Context, HttpContext.Current.Request);
                string arg = HttpUtility.UrlPathEncode(GetDownLoadUrl(_url)).Replace("+", "%20");
                ((Dictionary<string, object>)(object)val)["filepath"] = $"{appSiteOuterNetUrl}{arg}";
                ((Dictionary<string, object>)(object)val)["fileid"] = Guid.NewGuid().ToString("N");
                string fileName = GetFileName(_url);
                fileName = GetUrlFileName(fileName);
                ((Dictionary<string, object>)(object)val)["targetfilename"] = HttpUtility.UrlEncode(fileName);
                ((Dictionary<string, object>)(object)val)["pageid"] = ((AbstractDynamicFormPlugIn)this).View.PageId;
                ((AbstractDynamicFormPlugIn)this).View.AddAction("OpenClientLocalResource", (object)val);
                ((AbstractDynamicFormPlugIn)this).View.SendDynamicFormAction(((AbstractDynamicFormPlugIn)this).View);
                ((AbstractDynamicFormPlugIn)this).View.ShowMessage(ResManager.LoadKDString("附件正在加载中..", "002011000004903", (SubSystemType)2, new object[0]), (MessageBoxType)0);
                CacheUtil.SetCache(((AbstractDynamicFormPlugIn)this).Context.GetAreaCacheKey(), "OpenClientLocalResourceCall", ((AbstractDynamicFormPlugIn)this).View.PageId, (object)((AbstractDynamicFormPlugIn)this).View);
                WriteOnlineViewUserBehaviorLog("LocalViewService");
            }
            base.ButtonClick(e);
        }

        private void WriteOnlineViewUserBehaviorLog(string operateType)
        {
            Context ctx = ((AbstractDynamicFormPlugIn)this).View.Context;
            MainWorker.QuequeTask(ctx, (Action)delegate
            {
                string productVersion = DataCenterService.GetProductVersion(ctx);
                if (OSLogServiceHelper.IsOpen(ctx, (Kingdee.BOS.BusinessEntity.OSS.Enums.LogType)(LogType)2, 139))
                {
                    string text = ctx.CurrentUserTimeZone.UtcOffset.ToString();
                    UserBehaviorLog val = new UserBehaviorLog(139, ctx.KDPassportId, "BOS_FileDownLoad", "OpenButtonClick", "tbbtn_OnLineView", 0L, ((AbstractDynamicFormPlugIn)this).View.PageId);
                    val.ErpUserName = ctx.UserName;
                    ((BaseLogInfo)val).GSessionId = ctx.Gsid;
                    val.GDCID = ctx.GDCID;
                    val.DBID = ctx.DBId;
                    val.DBName = ctx.DataCenterName;
                    val.TimeZone = (text.StartsWith("-") ? text : ("+" + text));
                    val.ProductVersion = productVersion;
                    val.OperateType = operateType;
                    val.PrePageId = ((((AbstractDynamicFormPlugIn)this).View.ParentFormView == null) ? "" : ((AbstractDynamicFormPlugIn)this).View.ParentFormView.PageId);
                    UserBehaviorLog val2 = val;
                    OSLogServiceHelper.Put(ctx, (BaseLogInfo)(object)val2);
                }
            }, (Action<AsynResult>)delegate (AsynResult ar)
            {
                if (!ar.Success && ar.Exception != null)
                {
                    LoggerWithContext.Error(((AbstractDynamicFormPlugIn)this).View.Context, "BAS", "Error Message for Online View Queque Task", ar.Exception);
                }
            });
        }

        private string GetUrlFileName(string fileName)
        {
            Match match = Regex.Match(fileName, "\\?([^\\?]+=[^\\?]+&)*filename=", RegexOptions.IgnoreCase);
            if (match.Success)
            {
                string text = string.Empty;
                int num = match.Index + match.Length;
                int num2 = fileName.IndexOf("&", num);
                if (num2 == -1)
                {
                    num2 = fileName.Length;
                }
                if (num2 > num)
                {
                    text = StringUtils.SubStr(fileName, num, num2 - num, "");
                    try
                    {
                        text = Encoding.UTF8.GetString(Convert.FromBase64String(text));
                    }
                    catch
                    {
                    }
                }
                fileName = (string.IsNullOrWhiteSpace(text) ? Guid.NewGuid().ToString() : HttpUtility.UrlDecode(text));
            }
            return fileName;
        }

        private void DeleteFile(string url)
        {
            if (StringUtils.EqualsIgnoreCase(_isRetain, "true"))
            {
                return;
            }
            string fileName = GetFileName(url);
            if (!CheckFileNameIsValid(fileName))
            {
                return;
            }
            string physicalPath = PathUtils.GetPhysicalPath(KeyConst.TEMPFILEPATH, fileName);
            if (!File.Exists(physicalPath))
            {
                if (ObjectUtils.IsNullOrEmptyOrWhiteSpace((object)_customDir))
                {
                    return;
                }
                string text = default(string);
                if (!PathUtils.TryCheckFileNameIsValid(_customDir.Replace("/", ""), out text))
                {
                    LoggerWithContext.Error(((AbstractDynamicFormPlugIn)this).View.Context, "BOS", text, (Exception)null);
                    return;
                }
                physicalPath = PathUtils.GetPhysicalPath(_customDir, fileName);
                if (!File.Exists(physicalPath))
                {
                    return;
                }
            }
            int num = 2;
            int num2 = 64;
            IntPtr intPtr = new IntPtr(-1);
            IntPtr intPtr2 = _lopen(physicalPath, num | num2);
            if (intPtr2 == intPtr)
            {
                CloseHandle(intPtr2);
                return;
            }
            CloseHandle(intPtr2);
            try
            {
                FileUtil.DeleteFile(physicalPath);
                if (!ObjectUtils.IsNullOrEmptyOrWhiteSpace((object)_customDir))
                {
                    string text2 = default(string);
                    if (!PathUtils.TryCheckFileNameIsValid(_customDir.Replace("/", ""), out text2))
                    {
                        LoggerWithContext.Error(((AbstractDynamicFormPlugIn)this).View.Context, "BOS", text2, (Exception)null);
                        return;
                    }
                    string physicalPath2 = PathUtils.GetPhysicalPath(_customDir);
                    if (Directory.Exists(physicalPath2))
                    {
                        Directory.Delete(physicalPath2);
                    }
                }
                _downLoadUrlMap.TryRemove(url, out var value);
                if (!ObjectUtils.IsNullOrEmptyOrWhiteSpace((object)value))
                {
                    FileServerHelper.ClearFileTokenData(value);
                }
            }
            catch (UnauthorizedAccessException ex)
            {
                string text3 = string.Format(ResManager.LoadKDString("IIS进程没有足够的权限来删除文件{0}...\n如确定需要自动删除服务端文件，请联系服务器管理员对文件夹{1}给用户EveryOne赋予足够的操作权限", "002420030026206", (SubSystemType)2, new object[0]), physicalPath, PathUtils.GetPhysicalPath(KeyConst.TEMPFILEPATH));
                LoggerWithContext.Error(((AbstractDynamicFormPlugIn)this).View.Context, "BOS-FileDownloadPlugin", text3, (Exception)ex);
            }
            catch (Exception ex2)
            {
                LoggerWithContext.Error(((AbstractDynamicFormPlugIn)this).View.Context, "BOS-FileDownloadPlugin", "删除下载临时文件失败", ex2);
            }
        }

        private bool CheckFileNameIsValid(string fileName)
        {
            if (fileName.StartsWith("download.aspx", StringComparison.OrdinalIgnoreCase))
            {
                return true;
            }
            string text = default(string);
            if (!PathUtils.TryCheckFileNameIsValid(fileName, out text))
            {
                LoggerWithContext.Error(((AbstractDynamicFormPlugIn)this).View.Context, "BOS", "文件名不合法。", (Exception)new KDException("CheckFileNameIsValid", text));
                return false;
            }
            return true;
        }

        private void DeleteExportCenterFile(string fileId)
        {
            ExportServiceHelper.DeleteExportFile(((AbstractDynamicFormPlugIn)this).View.Context, fileId);
        }

        private void InitDownloadLink()
        {
            Control control = ((AbstractDynamicFormPlugIn)this).View.GetControl("FDownLoad");
            string fileName = string.Empty;
            if (!ObjectUtils.IsNullOrEmptyOrWhiteSpace((object)_url))
            {
                string text = HttpUtility.UrlPathEncode(GetDownLoadUrl(_url, out fileName)).Replace("+", "%20");
                fileName = SetFileNamePropertyValue(control, fileName);
                if (!KDConfiguration.Current.IsFileSaveAs)
                {
                    if ((int)((AbstractDynamicFormPlugIn)this).View.Context.ClientType == 1 && !SystemParameterServiceHelper.IsWpfDownloadByBrowser(((AbstractDynamicFormPlugIn)this).View.Context))
                    {
                        control.SetCustomPropertyValue("IsClickSave", (object)true);
                        control.SetCustomPropertyValue("ClickSaveUrl", (object)text);
                    }
                    else
                    {
                        control.SetCustomPropertyValue("url", (object)text);
                        control.SetCustomPropertyValue("IsFileUrl", (object)true);
                        control.InvokeControlMethod("UpdateRihgtMenu", (object[])null);
                    }
                }
                else
                {
                    control.SetCustomPropertyValue("IsClickSave", (object)true);
                    control.SetCustomPropertyValue("ClickSaveUrl", (object)text);
                }
            }
            if (!ObjectUtils.IsNullOrEmptyOrWhiteSpace((object)_linkText))
            {
                control.SetCustomPropertyValue("Text", (object)_linkText);
            }
            if (KDConfiguration.Current.AutomationTest)
            {
                control.SetCustomPropertyValue("Text", (object)fileName);
            }
        }

        private string SetFileNamePropertyValue(Control downloadControl, string fileName)
        {
            if (string.IsNullOrEmpty(fileName))
            {
                if (_url.Contains("?"))
                {
                    string[] array = _url.Split(new char[2] { '?', '&' }, StringSplitOptions.RemoveEmptyEntries);
                    string[] array2 = array;
                    foreach (string text in array2)
                    {
                        if (text.StartsWith("filename=", StringComparison.OrdinalIgnoreCase))
                        {
                            string text2 = StringUtils.SubStr(text, "filename=".Length, text.Length, "");
                            try
                            {
                                fileName = Encoding.UTF8.GetString(Extentions.Base64ToBytes(text2));
                            }
                            catch
                            {
                                fileName = text2;
                            }
                            break;
                        }
                    }
                }
                else if (File.Exists(_url))
                {
                    fileName = GetFileName(_url);
                }
            }
            downloadControl.SetCustomPropertyValue("FileName", (object)fileName);
            return fileName;
        }

        private void InitDownloadLinkList()
        {
            JSONArray val = new JSONArray();
            int num = 20;
            int num2 = 5;
            for (int i = 0; i < _urls.Count; i++)
            {
                string value = HttpUtility.UrlPathEncode(GetDownLoadUrl(_urls[i])).Replace("+", "%20");
                LinkBtnAppearance val2 = new LinkBtnAppearance();
                ((AbstractElement)val2).Key = "btnLink" + i;
                ((Appearance)val2).Caption = new LocaleValue($"part{i + 1}");
                ((Appearance)val2).Width = new LocaleValue("50");
                ((Appearance)val2).Visible = int.MaxValue;
                ((ControlAppearance)val2).Style = 0;
                if (i > 0 && i % 5 == 0)
                {
                    num2 += 20;
                    num = 20;
                }
                ((Appearance)val2).Top = new LocaleValue(num2.ToString());
                ((Appearance)val2).Left = new LocaleValue(num.ToString());
                num += 55;
                JSONObject val3 = ((ControlAppearance)val2).CreateControl();
                if ((int)((AbstractDynamicFormPlugIn)this).View.Context.ClientType == 1 && !SystemParameterServiceHelper.IsWpfDownloadByBrowser(((AbstractDynamicFormPlugIn)this).View.Context))
                {
                    ((Dictionary<string, object>)(object)val3)["xtype"] = "kddownlandlink";
                    ((Dictionary<string, object>)(object)val3)["isclicksave"] = true;
                    ((Dictionary<string, object>)(object)val3)["clicksaveurl"] = value;
                }
                else
                {
                    ((Dictionary<string, object>)(object)val3)["isfileurl"] = true;
                    ((Dictionary<string, object>)(object)val3)["url"] = value;
                }
                ((List<object>)(object)val).Add((object)val3);
            }
            PanelAppearance val4 = new PanelAppearance("FPanelLinks");
            ((ControlAppearance)val4).Dock = 5;
            JSONObject val5 = ((ControlAppearance)val4).CreateControl();
            ((Dictionary<string, object>)(object)val5)["items"] = val;
            ((AbstractDynamicFormPlugIn)this).View.GetControl<Panel>("FPanelLinks").ReplaceChildrenData(val5);
        }

        private string GetDownLoadUrl(string url)
        {
            string fileName;
            return GetDownLoadUrl(url, out fileName);
        }

        private string GetDownLoadUrl(string url, out string fileName)
        {
            fileName = string.Empty;
            if (ObjectUtils.IsNullOrEmptyOrWhiteSpace((object)url))
            {
                return string.Empty;
            }
            if (url.StartsWith("http", StringComparison.OrdinalIgnoreCase) || url.IndexOf("download.aspx", StringComparison.OrdinalIgnoreCase) > -1)
            {
                return url;
            }
            if (!url.TrimStart('/', '\\').StartsWith(KeyConst.TEMPFILEPATH, StringComparison.OrdinalIgnoreCase) && !url.TrimStart('/', '\\').StartsWith(KeyConst.DATATEMPLATE_PATH, StringComparison.OrdinalIgnoreCase))
            {
                return url;
            }
            fileName = GetFileName(url);
            string text = "";
            int num = url.LastIndexOf('/');
            int num2 = url.LastIndexOf('\\');
            if (num > -1 || num2 > -1)
            {
                text = url.Substring(0, (num > num2) ? num : num2);
            }
            string physicalPath = PathUtils.GetPhysicalPath(text, fileName);
            string downloadUrl = FileServerHelper.GetDownloadUrl(((AbstractDynamicFormPlugIn)this).View.Context, (DownloadIdType)1, physicalPath, new Dictionary<string, object>
        {
            { "ExpTime", 7200 },
            { "MaxTimesUsed", 5 },
            { "pv", 1 },
            { "pvl", 1 }
        });
            downloadUrl = $"{downloadUrl}&filename={Convert.ToBase64String(Encoding.UTF8.GetBytes(fileName))}";
            Func<string> valueFactory = delegate
            {
                Match match = Regex.Match(downloadUrl, "\\?id=([^&]+)&");
                string stringToUnescape = (match.Success ? match.Value.TrimEnd('&').Substring(4) : string.Empty);
                return Uri.UnescapeDataString(stringToUnescape);
            };
            _downLoadUrlMap.AddOrUpdate(url, (string key) => valueFactory(), (string key, string val) => valueFactory());
            return downloadUrl;
        }

        private string GetFileName(string url)
        {
            string text = string.Empty;
            string[] array = url.Split('/', '\\');
            if (array.Length > 0)
            {
                text = array[array.Length - 1];
            }
            return PathUtils.UrlDecode(text);
        }
    }
}
